//Copyright (c) 2018 Yardi Technology Limited. Http://www.kooboo.com 
//All rights reserved.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Kooboo.IndexedDB.Helper
{
    public class IndexHelper
    {

        public static void VerifyIndexType(Type type)
        {
            if (type == null)
            {
                throw new Exception("Invalid field name or keytype.");
            }

            if (type == typeof(string) || type == typeof(byte) || type == typeof(Int32) || type == typeof(Int64) || type == typeof(Int16) || type == typeof(DateTime) || type == typeof(Guid) || type == typeof(float) || type == typeof(double) || type == typeof(decimal))
            {
                return;
            }
            else
            {
                throw new Exception("only the following datatype are allowed to used as an index key: string, byte, int16,int32, int64, datetime, decimal, double, float, guid");
            }

        }

        public static List<IndexSetting> GenerateIndexsFromParameters(Type ValueType, ObjectStoreParameters parameters)
        {
            List<IndexSetting> indexlist = new List<IndexSetting>();

            // create the index setting. 
            foreach (var item in parameters.IndexList)
            {
                IndexSetting index = new IndexSetting();
                index.FieldName = item.Key;

                FieldInfo fieldinfo = ValueType.GetField(item.Key);

                if (fieldinfo != null)
                {
                    index.KeyType = fieldinfo.FieldType;
                }
                else
                {
                    //try get property. 
                    PropertyInfo propertyinfo = ValueType.GetProperty(item.Key);
                    if (propertyinfo != null)
                    {
                        index.KeyType = propertyinfo.PropertyType;
                    }
                    else
                    {
                        throw new Exception("field or property does not exists " + item);
                    }
                }

                index.unique = false;  /// this should always be false for all additional index.unique should be checked by contraints. 

                index.keyLength = Helper.KeyHelper.GetKeyLen(index.KeyType, index.keyLength);

                indexlist.Add(index);

            }

            return indexlist;
        }

        public static string GetIndexFileName(string objectfolder, string fieldname)
        {
            return System.IO.Path.Combine(objectfolder, fieldname + ".index");
        }


        public static Guid NewTimeGuid()
        {
            return NewTimeGuid(DateTime.UtcNow);
        }

        public static Guid NewTimeGuid(DateTime utcTime)
        {
            var tick = utcTime.Ticks;

            byte[] tickbytes = BitConverter.GetBytes(tick);

            tickbytes = tickbytes.Reverse().ToArray(); 

            var newid = Guid.NewGuid();

            var idbytes = newid.ToByteArray();

            byte[] lastid = new byte[16];

            System.Buffer.BlockCopy(tickbytes, 0, lastid, 0, 8);

            System.Buffer.BlockCopy(idbytes, 8, lastid, 8, 8);

            return new Guid(lastid);

        }

        // only for guid that is generated by our time guid. 
        public static DateTime ExtractTimeFromGuid(Guid id)
        {
            var bytes = id.ToByteArray();

            byte[] longbyte = new byte[8];

            System.Buffer.BlockCopy(bytes, 0, longbyte, 0, 8);

            longbyte = longbyte.Reverse().ToArray(); 

            var longtick = BitConverter.ToInt64(longbyte, 0);

            var time = new DateTime(longtick, DateTimeKind.Utc);

            return time;

        }


    }
}
